ActiveAdmin.register Stock do
  config.per_page = [50, 100, 500]
  permit_params :ts_code, :symbol, :name, :area, :industry, :cnspell, :market, :list_date, :act_name,
                :act_ent_type, :is_black, :is_choice, :buy_price, :sell_price, :is_held, :is_buy_point,
                :is_alert, :ma_alert, :choice_block_tag, :note, :is_long

  scope :is_held?, :default => true
  scope :is_choice?
  scope :is_alert?
  scope :is_long?
  scope :is_buy_point?
  scope :all

  # 自定义带确认的批量删除
  batch_action :batch_clear_is_choice, confirm: "批量删除自选", icon: "fas fa-trash-alt" do |ids|
    Stock.where(id: ids).update_all(is_choice: false)
    redirect_to admin_stocks_path
  end
  batch_action :batch_clear_is_alert, confirm: "批量删除告警", icon: "fas fa-trash-alt" do |ids|
    Stock.where(id: ids).update_all(is_alert: false)
    redirect_to admin_stocks_path
  end
  batch_action :batch_clear_is_held, confirm: "批量删除held", icon: "fas fa-trash-alt" do |ids|
    Stock.where(id: ids).update_all(is_held: false)
    redirect_to admin_stocks_path
  end

  index do
    selectable_column
    id_column
    column :name
    column :symbol
    column :price do |stock|
      "#{(JSON.parse $Redis.get(stock.symbol))["trade"]}" unless $Redis.get(stock.symbol).nil?
    end
    column :buy_price
    column :sell_price
    column :ma_alert
    column :is_held
    column :is_choice if params[:scope] != 'is_choice'
    column :is_long if params[:scope] != 'is_choice'
    column :is_black if params[:scope] != 'is_choice'
    column :is_alert if params[:scope] != 'is_choice'
    column :year_count
    column :is_buy_point
    column :change do |stock|
      "#{(JSON.parse $Redis.get(stock.symbol))["changepercent"]&.to_f.round(2)}%" unless $Redis.get(stock.symbol).nil?
    end
    column :ths_flow
    column :score
    column :volume_change
    column :choice_at if params[:scope] == 'is_choice'
    column :choice_block_tag if params[:scope] == 'is_choice'
    column :note
    actions
  end

  filter :name
  filter :symbol
  filter :note, if: proc { |context| context.params[:scope] == 'is_choice' }

  form do |f|
    f.inputs do
      f.input :name
      f.input :is_held, as: :boolean
      f.input :is_choice, as: :boolean
      f.input :is_long, as: :boolean
      f.input :is_black, as: :boolean
      f.input :is_alert, as: :boolean
      f.input :buy_price
      f.input :sell_price
      f.input :ma_alert
      f.input :choice_block_tag
      f.input :note
    end
    f.actions
  end

  sidebar '操作提示', only: [:edit, :new] do
    ul do
      li 'Ma alert   代表均线告警'
      li '小于0： -3  代表小于3日均线告警'
      li '大于0： 3   代表大于3日均线告警'
    end
  end

  show do
    @redis_stock = JSON.parse $Redis.get(resource.symbol)
    @ths_flow = RealTime.ths_flow stock.symbol
    # # 000001.SH: 上证指数, 399001.SZ: 深证成指, 399006.SZ: 创业版指数
    INDEX = { "3" => "399006.SZ", "0" => "399001.SZ", "6" => "000001.SH" }
    index_daily = $TusharePro.tushare_pro("index_daily", ts_code: INDEX[resource.symbol[0]]).first(120)

    attributes_table do
      row :name do |stock|
        link_to "#{stock.name}", "https://stockpage.10jqka.com.cn/#{stock.ts_code[0..5]}/", target: '_blank', rel: "noopener noreferrer"
      end
      row :symbol
      row :is_black
      row :is_buy_point


      row ('当前价格') { @redis_stock["trade"] }
      row ('涨幅') { @redis_stock["changepercent"] }
      row ('市值(亿)') { (@redis_stock["mktcap"].to_f / 10000).round(2) }
      row ('流通(亿)') { (@redis_stock["nmc"].to_f / 10000).round(2) }
      row ('市净率') { @redis_stock["pb"] }
      row ('市盈率') { @redis_stock["per"] }

      row ('近一年涨停') { resource.year_count }
      row ('资金流入(万)') do |stock|
        link_to "#{@ths_flow["title"]["je"]}", "https://stockpage.10jqka.com.cn/#{stock.symbol}/funds/#funds_sszjlx", target: '_blank', rel: "noopener noreferrer"
      end
      row ('量') { resource.volume_change }
      # TODO 判断趋势，per是什么意思？
      row ('趋势') { @redis_stock["per"] }
      row ('综合评分') { @ths_flow["score"] }

      panel "异动列表" do
        fluctuations = Fluctuation.where(code: resource.symbol)
        table_for fluctuations do
          column :title
          column :trend
          column :href do | fluctuation |
            link_to '查看详情', fluctuation.href
          end
          column :created_at do | fluctuation |
            fluctuation.created_at.strftime("%Y-%m-%d %H:%M")
          end
        end
      end

      div do
        stock.blocks.pluck(:name).each do |sk|
          span link_to "#{sk}", admin_block_path(Block.find_by_name(sk).id), target: '_blank', rel: "noopener noreferrer"
        end
      end

      panel "资金流入情况: 净流入#{@ths_flow["title"]["je"]}" do
        div id: 'flow', style: "width: 100%; height: 300px;"
        # 填充数据
        categories = { '大单' => { inflow: 0, outflow: 0 },
                       '中单' => { inflow: 0, outflow: 0 },
                       '小单' => { inflow: 0, outflow: 0 } }

        @ths_flow["flash"].each do |item|
          type, direction = item["name"].split(/(流入|流出)$/)
          value = item["sr"].to_f
          categories[type][direction == "流入" ? :inflow : :outflow] = value
        end

        # 生成数据集
        dataset = [
          ['product', '流入', '流出'],
          ['大单', categories['大单'][:inflow], categories['大单'][:outflow]],
          ['中单', categories['中单'][:inflow], categories['中单'][:outflow]],
          ['小单', categories['小单'][:inflow], categories['小单'][:outflow]]
        ]

        ['大单', '中单', '小单'].each do |type|
          inflow = @ths_flow["flash"].find { |x| x["name"].start_with?("#{type}流入") }["sr"].to_f
          outflow = @ths_flow["flash"].find { |x| x["name"].start_with?("#{type}流出") }["sr"].to_f
          div "#{type}净流入: #{(inflow - outflow).round(2)} 万"
        end

        script <<~JS.html_safe
          var chartDom11 = document.getElementById('flow');
          var myChart11 = echarts.init(chartDom11);
          var option11 = { 
            legend: {},
            tooltip: {},
            dataset: {
              source: #{raw dataset.to_json}
            },
            xAxis: { type: 'category' },
            yAxis: {},
            // Declare several bar series, each will be mapped
            // to a column of dataset.source by default.
            series: [{ type: 'bar' }, { type: 'bar' }]
          };
          option11 && myChart11.setOption(option11);
          myChart11.on('mouseover', function(params) {
            console.log(params.seriesName);
          });
          
          document.addEventListener('keydown', (e) => {
            if (['INPUT','TEXTAREA'].includes(e.target.tagName) || e.target.isContentEditable) return;
            if (e.key.toLowerCase() === 'e') {
              console.log(e);
              e.preventDefault();
              window.open('http://120.53.3.4/admin/stocks/#{resource.id}/edit', '_blank');
            }
          });
        JS
      end

      panel "#{resource.name} -- #{resource.symbol}" do
        k_lines = Tushare::Stock::Trading.get_k_data(resource.symbol).last(120)
        dates = k_lines.map { |x| x["date"] }
        closes = k_lines.map { |x| x["close"] }
        opens = k_lines.map { |x| x["open"] }
        highs = k_lines.map { |x| x["high"] }
        lows = k_lines.map { |x| x["low"] }
        datas = dates.each_with_index.map { |date, i| [date, opens[i], closes[i], lows[i], highs[i]] }

        div id: "k_line", style: "width: 100%; height: 600px;"
        script <<~JS.html_safe
          var chartDom = document.getElementById('k_line');
          var myChart = echarts.init(chartDom);
          var option;
          
          const upColor = '#ec0000';
          const upBorderColor = '#8A0000';
          const downColor = '#00da3c';
          const downBorderColor = '#008F28';
          // Each item: open，close，lowest，highest
          const data0 = splitData(#{raw datas.to_json});
          function splitData(rawData) {
            const categoryData = [];
            const values = [];
            for (var i = 0; i < rawData.length; i++) {
              categoryData.push(rawData[i].splice(0, 1)[0]);
              values.push(rawData[i]);
            }
            return {
              categoryData: categoryData,
              values: values
            };
          }
          function calculateMA(dayCount) {
            var result = [];
            for (var i = 0, len = data0.values.length; i < len; i++) {
              if (i < dayCount) {
                result.push('-');
                continue;
              }
              var sum = 0;
              for (var j = 0; j < dayCount; j++) {
                sum += +data0.values[i - j][1];
              }
              result.push(sum / dayCount);
            }
            return result;
          }
          option = {
            title: {
              text: "#{raw resource.name} + note: #{raw resource.note}",
              left: 0
            },
            tooltip: {
              trigger: 'axis',
              axisPointer: {
                type: 'cross'
              }
            },
            legend: {
              data: ['日K', 'MA5', 'MA10', 'MA20', 'MA30', 'MA60', 'MA120'],
              top: 20
            },
            grid: {
              left: '10%',
              right: '10%',
              bottom: '15%'
            },
            xAxis: {
              type: 'category',
              data: data0.categoryData,
              boundaryGap: false,
              axisLine: { onZero: false },
              splitLine: { show: false },
              min: 'dataMin',
              max: 'dataMax'
            },
            yAxis: {
              scale: true,
              splitArea: {
                show: true
              }
            },
            dataZoom: [
              {
                type: 'inside',
                start: 50,
                end: 100
              },
              {
                show: true,
                type: 'slider',
                top: '90%',
                start: 50,
                end: 100
              }
            ],
            tooltip: {
              trigger: 'axis',
              axisPointer: { type: 'cross' },
              formatter: function (params) {
                let dataIndex = params[0].dataIndex;
                let date = data0.categoryData[dataIndex];
                let open = data0.values[dataIndex][0].toFixed(2);
                let close = data0.values[dataIndex][1].toFixed(2);
                let low = data0.values[dataIndex][2].toFixed(2);
                let high = data0.values[dataIndex][3].toFixed(2);
                // console.log(params); 
                // 获取MA系列数据
                let ma3 = params.find(p => p.seriesName === 'MA3')?.value?.toFixed(2) || '-';
                let ma5 = params.find(p => p.seriesName === 'MA5')?.value?.toFixed(2) || '-';
                let ma10 = params.find(p => p.seriesName === 'MA10')?.value?.toFixed(2) || '-';
                let ma20 = params.find(p => p.seriesName === 'MA20')?.value?.toFixed(2) || '-';
                let ma30 = params.find(p => p.seriesName === 'MA30')?.value?.toFixed(2) || '-';
                let ma60 = params.find(p => p.seriesName === 'MA60')?.value?.toFixed(2) || '-';
                
                return `
                  <div style="font-size:14px;color:#666;line-height:1.8;">
                    <div>日期：${date}</div>
                    <div style="margin:5px 0;border-top:1px solid #eee;"></div>
                    <div>开盘：<span style="color:#333;font-weight:bold">${open}</span></div>
                    <div>收盘：<span style="color:${close >= open ? upColor : downColor}">${close}</span></div>
                    <div>最高：<span style="color:#333">${high}</span></div>
                    <div>最低：<span style="color:#333">${low}</span></div>
                    <div style="margin:5px 0;border-top:1px solid #eee;"></div>
                    <div>MA3：<span style="color:#F04B22">${ma3}</span></div>
                    <div>MA5：<span style="color:#FFA60F">${ma5}</span></div>
                    <div>MA10：<span style="color:#FFD111">${ma10}</span></div>
                    <div>MA20：<span style="color:#2B73AF">${ma20}</span></div>
                    <div>MA30：<span style="color:#9B1E64">${ma30}</span></div>
                    <div>MA60：<span style="color:#0EB0C9">${ma60}</span></div>
                    <div style="margin:5px 0;border-top:1px solid #eee;"></div>
                    <div>Index：<span style="color:#0EB0C9">${ (#{raw index_daily.map { |d| ["#{d['trade_date'][0..3]}-#{d['trade_date'][4..5]}-#{d['trade_date'][6..7]}", d['pct_chg'].round(2)] }.to_h.to_json}[date] || '-') }</span></div>
                    <div>操作建议：</div>
                    <div>买入价：<span style="color:#43b244">#{resource.buy_price}</span></div>
                    <div>卖出价：<span style="color:#ff4500">#{resource.sell_price}</span></div>
                  </div>
                `;
              }
            },
            series: [
              {
                name: '日K',
                type: 'candlestick',
                data: data0.values,
                itemStyle: {
                  color: upColor,
                  color0: downColor,
                  borderColor: upBorderColor,
                  borderColor0: downBorderColor
                },
                markPoint: {
                  label: {
                    formatter: function (param) {
                      return param != null ? Math.round(param.value) + '' : '';
                    }
                  },
                  data: [
                    {
                      name: 'Mark',
                      coord: ['2013/5/31', 2300],
                      value: 2300,
                      itemStyle: {
                        color: 'rgb(41,60,85)'
                      }
                    },
                    {
                      name: 'highest value',
                      type: 'max',
                      valueDim: 'highest'
                    },
                    {
                      name: 'lowest value',
                      type: 'min',
                      valueDim: 'lowest'
                    },
                    {
                      name: 'average value on close',
                      type: 'average',
                      valueDim: 'close'
                    }
                  ],
                  tooltip: {
                    formatter: function (param) {
                      return param.name + '<br>' + (param.data.coord || '');
                    }
                  }
                },
                markLine: {
                  symbol: ['none', 'none'],
                  data: [
                    [
                      {
                        name: 'from lowest to highest',
                        type: 'min',
                        valueDim: 'lowest',
                        symbol: 'circle',
                        symbolSize: 10,
                        label: {
                          show: false
                        },
                        emphasis: {
                          label: {
                            show: false
                          }
                        }
                      },
                      {
                        type: 'max',
                        valueDim: 'highest',
                        symbol: 'circle',
                        symbolSize: 10,
                        label: {
                          show: false
                        },
                        emphasis: {
                          label: {
                            show: false
                          }
                        }
                      }
                    ],
                    {
                      name: 'min line on lowest',
                      type: 'min',
                      valueDim: 'lowest'
                    },
                    {
                      name: 'max line on highest',
                      type: 'max',
                      valueDim: 'highest'
                    },
                    {
                      name: 'buy_price',
                      yAxis: "#{raw resource.buy_price}",       // 水平直线（固定Y轴值）
                      lineStyle: {
                        type: 'dotted', // 虚线类型
                        color: '#43b244',
                        width: 2
                      }
                    },
                    {
                      name: 'sell_price',
                      yAxis: "#{raw resource.sell_price}",       // 水平直线（固定Y轴值）
                      lineStyle: {
                        type: 'dotted', // 虚线类型
                        color: '#ff4500',
                        width: 2
                      }
                    }
                  ]
                }
              },
              {
                name: 'MA3',
                type: 'line',
                data: calculateMA(3),
                smooth: true,
                symbol: 'circle',       // 点形状（默认空心圆） 
                symbolSize: 3,          // 点大小（单位像素）
                lineStyle: {
                  color: '#F04B22',    // 线条颜色
                  width: 2,            // 线宽（默认1）
                  type: 'line',      // 线型（solid/dashed/dotted）
                  opacity: 1,        // 透明度（0-1）
                }
              },
              {
                name: 'MA5',
                type: 'line',
                data: calculateMA(5),
                smooth: true,
                symbol: 'circle',       // 点形状（默认空心圆） 
                symbolSize: 3,          // 点大小（单位像素）
                lineStyle: {
                  color: '#FFA60F',    // 线条颜色
                  width: 2,            // 线宽（默认1）
                  type: 'line',      // 线型（solid/dashed/dotted）
                  opacity: 1,        // 透明度（0-1）
                  curveness: 0.3       // 曲率（仅对平滑曲线有效）
                }
              },
              {
                name: 'MA10',
                type: 'line',
                data: calculateMA(10),
                smooth: true,
                symbol: 'circle',       // 点形状（默认空心圆） 
                symbolSize: 3,          // 点大小（单位像素）
                lineStyle: {
                  color: '#FFD111',    // 线条颜色
                  opacity: 0.5
                }
              },
              {
                name: 'MA20',
                type: 'line',
                data: calculateMA(20),
                smooth: true,
                symbol: 'circle',       // 点形状（默认空心圆） 
                symbolSize: 3,          // 点大小（单位像素）
                lineStyle: {
                  color: '#2B73AF',    // 线条颜色
                  opacity: 1
                }
              },
              {
                name: 'MA30',
                type: 'line',
                data: calculateMA(30),
                smooth: true,
                symbol: 'circle',       // 点形状（默认空心圆） 
                symbolSize: 3,          // 点大小（单位像素）
                lineStyle: {
                  color: '#9B1E64',    // 线条颜色
                  opacity: 0.5
                }
              },
              {
                name: 'MA60',
                type: 'line',
                data: calculateMA(60),
                smooth: true,
                symbol: 'circle',       // 点形状（默认空心圆） 
                symbolSize: 3,          // 点大小（单位像素）
                lineStyle: {
                  color: '#0EB0C9',    // 线条颜色
                  opacity: 1
                }
              }
            ]
          };
          option && myChart.setOption(option);
          myChart.on('click', function(params) {
            var stockId = #{resource.id};
            window.open("http://wyyzrx.com/admin/stocks/" + stockId + '/edit');
          });
        JS
      end
      panel "近期累计资金流入" do
        div id: "flow_everyday", style: "width: 100%; height: 300px;"
        div id: "flow_sum", style: "width: 100%; height: 300px;"
        moneyflow = $TusharePro.tushare_pro("moneyflow", ts_code: resource.ts_code,  "start_date": trade_date(20), "end_date": Time.now.strftime("%Y%m%d"))
        created_ats = moneyflow.sort_by { |x| x["trade_date"] }.map { |x| "#{x['trade_date'][4..5]}-#{x['trade_date'][6..7]}" }
        # 如果当天数据还没出来，则补上当天的数据
        moneyflow << {
          "trade_date" => Time.now.strftime("%Y%m%d"),
          "net_mf_amount" => @ths_flow["title"]["je"].to_f
        } if moneyflow.last["trade_date"] != Time.now.strftime("%Y%m%d")
        everyday_net_amounts = moneyflow.sort_by { |x| x["trade_date"] }.map { |x| (x["net_mf_amount"].to_f).round(2) }
        # 计算每天流入的累计值
        sum_net_amounts = everyday_net_amounts.each_with_index.map { |x, i| everyday_net_amounts.first(i + 1).sum.round(2) }
        script <<~JS.html_safe
          var flow_everyday = document.getElementById('flow_everyday');
          var flow_sum = document.getElementById('flow_sum');
          var flow_everyday_Chart = echarts.init(flow_everyday);
          var flow_sum_Chart = echarts.init(flow_sum);
          var flow_everyday_option;
          var flow_sum_option;

          flow_everyday_option = {
            xAxis: {
              type: 'category',
              data: #{raw created_ats}
            },
            yAxis: {
              type: 'value'
            },
            series: [
              {
                data: #{raw everyday_net_amounts},
                type: 'line'
              }
            ]
          };
          flow_sum_option = {
            xAxis: {
              type: 'category',
              data: #{raw created_ats}
            },
            yAxis: {
              type: 'value'
            },
            series: [
              {
                data: #{raw sum_net_amounts},
                type: 'line'
              }
            ]
          };

          // 响应式调整
          flow_everyday_option && flow_everyday_Chart.setOption(flow_everyday_option);
          flow_sum_option && flow_sum_Chart.setOption(flow_sum_option);
        JS
      end

      # div do
      #   raw $Markdown.render(Qwen.open_ai_stock("#{stock.symbol} -- #{stock.name}"))
      # end
    end
  end
end
